package com.qianfeng.smsplatform.search.service.impl;


//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼            BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  


import com.fasterxml.jackson.databind.ObjectMapper;
import com.qianfeng.smsplatform.common.model.Standard_Report;
import com.qianfeng.smsplatform.search.service.SearchService;
import com.qianfeng.smsplatform.search.utils.SearchUtil;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by jackiechan on 2021/4/10 20:10
 *
 * @author jackiechan
 */
@Service
public class SearchServiceImpl implements SearchService {
    static final Logger LOGGER = LoggerFactory.getLogger(SearchServiceImpl.class);

    @Autowired
    private RestHighLevelClient client;
    @Autowired
    private ObjectMapper objectMapper;


    @Value("${spring.data.elasticsearch.index.name}")
    private String index;

    @Value("${spring.data.elasticsearch.index.type}")
    private String type;

    @Override
    public void add(String json) throws Exception {
        IndexRequest indexRequest = new IndexRequest(index, type);
        indexRequest.source(json, XContentType.JSON);
        client.index(indexRequest, RequestOptions.DEFAULT);
    }

    @Override
    public void createIndexAndType() throws Exception {
        if (!existsIndex(index)) {
            CreateIndexRequest createIndexRequest = new CreateIndexRequest(index);
            SearchUtil.buildingSetting(createIndexRequest);
            SearchUtil.buildingMapping(createIndexRequest, type);
            client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        }
    }

    @Override
    public void update(Standard_Report report) throws Exception {
        String msgId = report.getMsgId();
        String id = termQueryId(msgId);
        if (id == null) {
            LOGGER.error("当前消息id没有查到对应的数据");
            return;
        }
        HashMap docMap = new HashMap();
        docMap.put("reportState", report.getState());
        docMap.put("errorCode", report.getErrorCode());
        UpdateRequest request = new UpdateRequest(index, type, id).doc(docMap);
        client.update(request, RequestOptions.DEFAULT);
    }

    @Override
    public String termQueryId(String msgId) throws Exception {
        SearchRequest request = new SearchRequest(index);
        request.types(type);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.termQuery("msgid",msgId));
        request.source(searchSourceBuilder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        if (hits.totalHits>0) {
            SearchHit[] hitsHits = hits.getHits();
            return hitsHits[0].getId();
        }
        return null;
    }

    @Override
    public boolean existsIndex(String index) throws Exception {
        GetIndexRequest request = new GetIndexRequest();
        request.indices(index);
        return client.indices().exists(request, RequestOptions.DEFAULT);
    }

    @Override
    public List<Map> search(String params) throws Exception {
        List<Map> result = new ArrayList<>();
        Map map = objectMapper.readValue(params, Map.class);//将所有的查询条件转换为 map
        SearchSourceBuilder searchSourceBuilder = SearchUtil.builSearachSource(map);

        Integer start = (Integer) map.get("start");
        Integer rows = (Integer) map.get("rows");
        searchSourceBuilder.from(start == null ? 0 : start);
        searchSourceBuilder.size(rows == null ?20 : rows);

        String keyword = (String) map.get("keyword");//关键字

        if (!StringUtils.isEmpty(keyword)) {
            //高亮
            String highLightPreTag = (String) map.get("highLightPreTag");//前半段标签
            String highLightPostTag = (String) map.get("highLightPostTag");//前半段标签
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            highlightBuilder.requireFieldMatch(false).field("messageContent").preTags(highLightPreTag).postTags(highLightPostTag);
            highlightBuilder.numOfFragments(0);
            searchSourceBuilder.highlighter(highlightBuilder);
        }


        SearchRequest request = new SearchRequest(index);
        request.types(type);
        request.source(searchSourceBuilder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        SearchHits searchHits = response.getHits();

        for (SearchHit hit : searchHits) {
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            if (!StringUtils.isEmpty(keyword)) {
                HighlightField highlightField = hit.getHighlightFields().get("messageContent");
                if (highlightField != null) {//有高亮
                    Text[] fragments = highlightField.fragments();
                    if (fragments != null) {
                        Text fragment = fragments[0];
                        sourceAsMap.put("messageContent", fragment.toString());//将原始结果中的高亮字段对应的内容替换为高亮的数据
                    }
                }
            }
            result.add(sourceAsMap);
        }


        return result;
    }

    @Override
    public long count(String params) throws Exception {
        Map map = objectMapper.readValue(params, Map.class);//将所有的查询条件转换为 map
        SearchSourceBuilder searchSourceBuilder = SearchUtil.builSearachSource(map);
        SearchRequest request = new SearchRequest(index);
        request.types(type);
        request.source(searchSourceBuilder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        return response.getHits().getTotalHits();
    }

    @PostConstruct
    public void init() {
        try {
            createIndexAndType();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
